/**
 * 
 */
package edu.umd.clip.lm.model.training.metrics;

import org.w3c.dom.Element;

import edu.umd.clip.lm.model.training.*;
import edu.umd.clip.lm.util.ConstCountDistribution;
import edu.umd.clip.lm.util.Long2IntMap;
import edu.umd.clip.lm.util.ProbMath;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class ConditionalEntropyMetrics extends ContextVariableMetrics {

	/**
	 * @param orderContextVariables
	 * @param name
	 */
	public ConditionalEntropyMetrics() {
		super("H(w|x)");
	}

	/**
	 * @param elem
	 */
	public ConditionalEntropyMetrics(Element elem) {
		super(elem);
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.ContextVariableMetrics#computeScore(edu.umd.clip.lm.model.training.NewTrainer.ContextVariableStats)
	 */
	@Override
	public double computeScore(ContextVariable ctxVar, ContextVariableStats stat) {
		long totalCount = 0;
		double condEntropy = 0;
		for(Object d : stat.x2wDistributions.values()) {
			ConstCountDistribution dist = (ConstCountDistribution) d;
			
			long keys[] = dist.keys();
			long counts[] = dist.values();
			for(int i=0; i<keys.length; ++i) {
				condEntropy -= counts[i] * ProbMath.log2(counts[i]);
			}
			condEntropy += dist.getTotalCount() * ProbMath.log2(dist.getTotalCount());
			totalCount += dist.getTotalCount();
		}
		condEntropy /= totalCount;
		return condEntropy;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.ContextVariableMetrics#needContextVarCounts()
	 */
	@Override
	public boolean needContextVarCounts() {
		return false;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.ContextVariableMetrics#needVarToWordCounts()
	 */
	@Override
	public boolean needVarToWordCounts() {
		return true;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.ContextVariableMetrics#needWordCounts()
	 */
	@Override
	public boolean needWordCounts() {
		return false;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.ContextVariableMetrics#needWordToVarCounts()
	 */
	@Override
	public boolean needWordToVarCounts() {
		return false;
	}

	@Override
	public String toString() {
		return "ConditionalEntropyMetrics []";
	}

}
